<template>
    <div>
        <!-- 一，面包屑导航区域 -->
        <el-breadcrumb separator-class="el-icon-arrow-right">
            <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
            <el-breadcrumb-item>权限管理</el-breadcrumb-item>
            <el-breadcrumb-item>角色列表</el-breadcrumb-item>
        </el-breadcrumb>
        <!-- 二，卡片视图区域 -->
        <el-card>
            <!-- 1,添加角色按钮，layout，行列 -->
            <el-row>
                <el-col>
                    <el-button type="primary" @click="addDialogVisible = true">添加角色</el-button>
                </el-col>
            </el-row>
            <!-- 2,角色列表 -->
            <el-table :data="rolelist" border stripe>
                <!-- 展开列 -->
                <el-table-column type="expand" label="" width="50">
                    <template slot-scope="scope">
                        <!-- <pre> {{scope.row}}</pre> -->
                        <!-- 栅格布局，3层渲染 -->
                        <el-row v-for="(items1, index1) in scope.row.children" :key="items1.id"
                            :class="['bdbottom', index1 === 0 ? 'bdtop' : '', 'vcenter']">
                            <!-- 渲染一级权限 -->
                            <el-col :span="4">
                                <el-tag closable @close="removeRightById(scope.row, items1.id)">{{ items1.authName }}
                                </el-tag>
                                <i class="el-icon-caret-right"></i>
                            </el-col>
                            <!-- 渲染二三级权限 -->
                            <el-col :span="20">
                                <el-row v-for="(items2, index2) in items1.children" :key="items2.id"
                                    :class="[index2 === 0 ? '' : 'bdtop', 'vcenter']">
                                    <!-- 二级 -->
                                    <el-col :span="5">
                                        <el-tag type="success" closable @close="removeRightById(scope.row, items2.id)">
                                            {{ items2.authName }}</el-tag>
                                        <i class="el-icon-caret-right"></i>
                                    </el-col>
                                    <!-- 三级 -->
                                    <el-col :span="19">
                                        <el-tag v-for="(items3) in items2.children" :key="items3.id" type="warning"
                                            closable @close="removeRightById(scope.row, items3.id)">{{ items3.authName
                                            }}
                                        </el-tag>
                                    </el-col>
                                </el-row>
                            </el-col>
                        </el-row>
                    </template>
                </el-table-column>
                <!-- 索引号 -->
                <el-table-column type="index" label="#" width="50">
                </el-table-column>
                <el-table-column prop="id" label="id" width="50">
                </el-table-column>
                <el-table-column prop="roleName" label="角色名称" width="180">
                </el-table-column>
                <el-table-column prop="roleDesc" label="角色描述" width="180">
                </el-table-column>
                <el-table-column label="操作">
                    <template slot-scope="scope">
                        <el-button type="primary" icon="el-icon-edit" size="mini" @click="showEditDialog(scope.row.id)">
                            修改</el-button>
                        <el-button type="danger" icon="el-icon-delete" size="mini"
                            @click="removeRoleById(scope.row.id)">删除</el-button>
                        <el-button type="warning" icon="el-icon-setting" size="mini"
                            @click="showSetRightDialog(scope.row)">分配权限
                        </el-button>
                    </template>
                </el-table-column>
            </el-table>
        </el-card>
        <!-- 三，修改角色的对话框 -->
        <el-dialog title="修改角色" :visible.sync="editDialogVisible" width="50%" @close="editDialogClosed">
            <el-form :model="editForm" :rules="editFormRules" ref="editFormRef" label-width="70px">
                <el-form-item label="角色名称">
                    <el-input v-model="editForm.roleName" prop="roleName"></el-input>
                </el-form-item>
                <el-form-item label="角色描述" prop="roleDesc">
                    <el-input v-model="editForm.roleDesc"></el-input>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="editDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="addRolesInfo()">确 定</el-button>
            </span>
        </el-dialog>
        <!-- 四,添加改角色的对话框 -->
        <el-dialog title="添加角色" :visible.sync="addDialogVisible" width="50%" @close="addDialogClosed">
            <el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="70px">
                <el-form-item label="角色名称">
                    <el-input v-model="addForm.roleName" prop="roleName"></el-input>
                </el-form-item>
                <el-form-item label="角色描述" prop="roleDesc">
                    <el-input v-model="addForm.roleDesc"></el-input>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="addDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="addRoles()">确 定</el-button>
            </span>
        </el-dialog>
        <!-- 五，分配权限对话框 -->
        <el-dialog title="分配权限" :visible.sync="SetRightDialogVisible" width="50%" @closed="SetRightDialogClosed()">
            <!-- 树形控件 -->
            <el-tree :data="rightslist" :props="treeProps" default-expand-all node-key="id" ref="treeRef" show-checkbox
                :default-checked-keys="defKeys">
            </el-tree>
            <span slot="footer" class="dialog-footer">
                <el-button @click="SetRightDialogVisible = false">取 消</el-button>
                <el-button type="primary" @click="SetRights()">确 定</el-button>
            </span>
        </el-dialog>
    </div>
</template>
<!-- 权限管理组件。
1，新建权限组件，注册路由。布局开始，面包屑路径导航栏。 卡片区域。添加按钮。发送请求获取角色列表。data定义好接收数组。
2，接着渲染出来，el-table,索引列type="index" ，展开列type="expand"，完善添加、编辑、删除用户功能。
3，接着，展开列：slot-scope="scope",3层for循环，栅格布局，el-row，el-col，加样式，加图标三角。解决拉框换行问题，#app加公共样式min-width：1366px.给一级二级加个居中样式vcenter，,
3，接着三级权限加可移除标签tag-closable，加事件@close="removeRightById(scope.row,items3.id)"，弹框this.$confirm，发送删除请求。完善删除后重新渲染关闭当下展开列问题，不建议整个页面全部渲染this.getRolesList(),而是直接赋值删除后响应回来的那些数据, role.children = res.data。
4，接着复制closable @close="removeRightById(scope.row, items3.id)"到二级一级进行，修改items3.id，
5，接着完善分配权限。对话框，事件，树形el-tree，按需导入使用，添加 :props属性:props="treeProps",data中定义treeProps 树形控件属性绑定对象,添加复选框show-checkbox。注意tree的各个属性。默认选中节点id :default-checked-keys="defKeys"，默认勾选的节点的 key 的数组，data定义defKeys数组，默认勾选渲染，定义方法getLeafKeys（），获取默认勾选数组。还有个bug,每次点击分配权限后，关闭要清空原本渲染数组？加SetRightDialogClosed（），
接着点击确定按钮函数SetRights()：获取节点ID，发送请求。el-tree自带2个方法getCheckedNodes和getHalfCheckedNodes，用展开运算符拼接数组，记得点击分配的时候保存this.roleId = role.id //这里获取当前被点击的角色的id。
6，完善用户列表 的分配角色功能。在User.vue组件完善。


-->
<script>
export default {
    data() {
        return {
            // 角色列表数据
            rolelist: [],
            // 角色修改对话框显示隐藏
            editDialogVisible: false,
            // 角色修改对话框数据
            editForm: [],
            // 角色修改对话框表单校验
            editFormRules: {
                roleDesc: [
                    { required: true, message: '请输入角色描述', trigger: 'blur' },
                    { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
                ],
                roleName: [
                    { required: true, message: '请输入角色描述', trigger: 'blur' },
                    { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
                ],
            },

            // 添加角色数据列表,注意这里，
            addForm: {
                roleName: '',
                roleDesc: '',
            },
            //  添加角色数据对话框显示隐藏
            addDialogVisible: false,
            // 添加角色对话框表单校验
            addFormRules: {
                roleDesc: [
                    { required: true, message: '请输入角色描述', trigger: 'blur' },
                    { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
                ],
                roleName: [
                    { required: true, message: '请输入角色描述', trigger: 'blur' },
                    { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
                ],
            },

            //分配权限对话框，显示隐藏
            SetRightDialogVisible: false,
            //分配权限列表数据
            rightslist: [],
            // 树形控件属性绑定对象
            treeProps: {
                label: 'authName',
                children: 'children'
            },
            //分配权限默认选中的节点id数组
            defKeys: [],
            //当前即将分配权限的角色id
            roleId: '',
        }
    },
    created() {
        // 获取角色列表
        this.getRolesList()
    },
    methods: {

        // 获取角色列表，发送请求
        async getRolesList() {
            const { data: res } = await this.$http.get('roles')
            console.log(res)
            if (res.meta.status !== 200) {
                return this.$message.error('获取角色列表失败')
            }
            this.rolelist = res.data
            console.log(this.rolelist)
        },

        // 显示修改角色对话框，根据id，发送请求
        async showEditDialog(id) {
            console.log(id)
            const { data: res } = await this.$http.get('roles/' + id)
            console.log(res)
            if (res.meta.status !== 200) {
                return this.$message.error('获取角色列表失败')
            }
            this.editForm = res.data
            this.editDialogVisible = true

        },

        // 关闭修改角色对话框，重置表单
        editDialogClosed() {
            this.$refs.editFormRef.resetFields()
        },

        // 修改角色对话框，确定提交，发送请求
        addRolesInfo() {
            this.$refs.editFormRef.validate(async valid => {
                console.log(valid)
                if (!valid)
                    return
                console.log('修改角色失败')
                const { data: res } = await this.$http.put('roles/' + this.editForm.roleId,
                    {
                        roleDesc: this.editForm.roleDesc,
                        roleName: this.editForm.roleName
                    })
                console.log(res)
                // 如果
                if (res.meta.status !== 200)
                    return this.$message.error(res.meta.msg)
                // 否则
                this.$message.success(res.meta.msg)
                this.editDialogVisible = false

            });
        },

        // 删除角色，发送请求
        async removeRoleById(id) {
            // 弹窗
            const confirmResult = await this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning',
                center: true
            }).catch(err => err);
            console.log(confirmResult)
            // 如果用户确认删除，则返回值为字符串 confirm
            // 如果用户取消了删除，则返回值为字符串 cancel
            if (confirmResult !== 'confirm')
                return this.$message.info('已经取消删除')
            // 请求
            const { data: res } = await this.$http.delete('roles/' + id)
            console.log(res)
            if (res.meta.status != 200)
                return this.$message.error(res.meta.msg)
            this.$message.success(res.meta.msg)
            this.getRolesList()
        },

        // 添加角色,提交
        async addRoles() {
            this.$refs.addFormRef.validate(async valid => {
                console.log(valid)
                if (!valid)
                    return console.log('添加角色失败')
                const { data: res } = await this.$http.post('roles', this.addForm)
                console.log(res)
                if (res.meta.status !== 201)
                    return this.$message.error(res.meta.msg)
                this.$message.success(res.meta.msg)
                this.addDialogVisible = false
                this.getRolesList()
            })
        },

        // 添加角色对话框,关闭，重置
        addDialogClosed() {
            this.$refs.addFormRef.resetFields()

        },

        // 移除三级权限
        async removeRightById(role, rightId) {
            const confirmResult = await this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).catch(err => err)
            if (confirmResult !== 'confirm') {
                return this.$message.info('已取消删除')
            }
            // console.log('确定删除')
            // 接着发送请求
            const { data: res } = await this.$http.delete(`roles/${role.id}/rights/${rightId}`)
            console.log(res)
            if (res.meta.status !== 200) {
                return this.$message.error('删除失败' + res.meta.msg)
            }
            // 如果成功
            console.log(res.meta.msg)
            // this.getRolesList() 不建议，这样子会整个渲染，展开列会回缩回去回复原样，
            role.children = res.data
        },

        // 分配权限对话框，发送请求获取数据，树形结构，显示
        async showSetRightDialog(role) {
            const { data: res } = await this.$http.get('rights/tree')
            // console.log(res)
            this.roleId = role.id //这里获取当前被点击的角色的id
            if (res.meta.status !== 200) {
                return this.$message.error('失败' + res.meta.msg)
            }
            this.rightslist = res.data //获取到的列表赋值到data中
            this.getLeafKeys(role, this.defKeys)  //调用递归函数渲染默认被选节点
            // this.$message.success('成功' + res.meta.msg)
            this.SetRightDialogVisible = true
        },

        //分配权限对话框，打开，把默认选中的三级的id渲染到树形上，默认勾选加载，属性绑定，递归形式，// 通过递归的形式，获取角色下所有三级权限的id，并保存到 defKeys 数组中，
        getLeafKeys(node, arr) {
            if (!node.children) {              //三级节点
                return arr.push(node.id)
            }
            // 如果不是三级节点，继续调用递归
            node.children.forEach(item => this.getLeafKeys(item, arr))
        },
        // 监听分配权限对话框的关闭事件,清空数组
        SetRightDialogClosed() {
            this.defKeys = []
        },

        //分配权限对话框，确定按钮，发送请求，展开运算符...
        async SetRights() {
            const keys = [
                ...this.$refs.treeRef.getCheckedKeys(),
                ...this.$refs.treeRef.getHalfCheckedKeys()
            ]

            const idStr = keys.join(',')

            const { data: res } = await this.$http.post(
                `roles/${this.roleId}/rights`,
                { rids: idStr }
            )

            if (res.meta.status !== 200) {
                return this.$message.error('分配权限失败！')
            }

            this.$message.success('分配权限成功！')
            this.getRolesList()
            this.SetRightDialogVisible = false

        },

        // 分配角色对话框，显示
        setRole(){
            this.setRoleDialogVisible = true 
        }
    },

}
</script>

<style lang="less" scoped>
.el-tag {
    margin-top: 7px;
}

// 展开列第一列样式
.bdtop {
    border-top: 1px solid green;
}

.bdbottom {
    border-bottom: 1px solid green;
}

.vcenter {
    display: flex;
    align-items: center;
}
</style>